package com.bluexmicro.ota2.ui.screen.asset

import android.bluetooth.le.ScanResult
import android.content.Context
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.bluexmicro.ota.FirmwareHelper
import com.bluexmicro.ota.asset.AssetBean
import com.bluexmicro.ota.asset.AssetProcess
import com.bluexmicro.ota.asset.AssetType
import com.bluexmicro.ota2.ui.screen.dfu.TimeConsuming
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.launch
import java.io.File
import java.lang.Exception
import java.util.zip.CRC32

class AssetViewModel : ViewModel() {


    val type = mutableStateOf(AssetType.FACE)
    val item = mutableStateOf<AssetBean?>(null)
    val target = mutableStateOf<ScanResult?>(null)
    val progress = mutableStateOf(-1f)

    val updating = derivedStateOf {
        progress.value >= 0f
    }

    val canUpdate = derivedStateOf {
        item.value != null && target.value != null && updating.value.not()
    }

    //失败
    val error = mutableStateOf<String?>(null)

    //成功
    val timeConsuming = mutableStateOf<TimeConsuming?>(null)

    fun onFileSelected(asset: File) = viewModelScope.launch(Dispatchers.IO) {
        try {
            val rawData = FirmwareHelper.loadBinary(asset) ?: return@launch
            val crc32 = CRC32()
            crc32.update(rawData)
            val crc32Value = crc32.value.toInt()
            item.value = AssetBean(type.value, asset.name, rawData, crc32Value)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun onDeviceSelected(scanResult: ScanResult) {
        target.value = scanResult
    }

    fun startUpdate(context: Context) = viewModelScope.launch(Dispatchers.Default) {
        var setupTimeConsuming = 0L
        var updateTimeConsuming: Long
        val asset = AssetProcess()
        val process = try {
            progress.value = 0f
            val anchor1 = System.currentTimeMillis()
            asset.initialize(context, target.value!!.device).apply {
                setupTimeConsuming = System.currentTimeMillis() - anchor1
            }
        } catch (e: Exception) {
            error.value = e.message ?: "Unknown Error"
            progress.value = -1f
            null
        }
        process?.apply {
            val anchor2 = System.currentTimeMillis()
            update(item.value!!)
                .catch {
                    error.value = it.message ?: "Unknown Error"
                    progress.value = -1f
                }.collect {
                    progress.value = it
                }
            updateTimeConsuming = System.currentTimeMillis() - anchor2
            timeConsuming.value = TimeConsuming(setupTimeConsuming, updateTimeConsuming)
            delay(500)
            progress.value = -1f
            release()
        }
    }

}